package com.xlh.openai.service.impl;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.lang.generator.UUIDGenerator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson2.util.UUIDUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xlh.openai.dao.ExchangeCodeDao;
import com.xlh.openai.dto.ExchangeCodeExportDTO;
import com.xlh.openai.entity.ExchangeCodeEntity;
import com.xlh.openai.entity.ProductEntity;
import com.xlh.openai.entity.WechatUserEntity;
import com.xlh.openai.entity.enums.UsedStatus;
import com.xlh.openai.exception.ServiceException;
import com.xlh.openai.service.ExchangeCodeService;
import com.xlh.openai.service.ProductService;
import com.xlh.openai.service.WechatUserService;
import com.xlh.openai.utils.ExcelUtil;
import io.swagger.annotations.ApiModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Service("exchangeCodeService")
public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeDao, ExchangeCodeEntity> implements ExchangeCodeService {

    @Autowired
    private HttpSession session;

    @Autowired
    private WechatUserService wechatUserService;

    @Autowired
    private ProductService productService;



    /**
     * openId cache
     */
    private Cache<String,Integer> openIdCache = CacheUtil.newTimedCache(10*60*1000);
    /**
     * 最大错误次数
     */
    private Integer maxErrorTime = 10;

    @Override
    @Transactional(rollbackForClassName = {"Exception"})
    public void exchange(String code) {

        WechatUserEntity wechatUser = wechatUserService.getLoginUserInfo(session);
        Integer exchangeTime = openIdCacheIncrement(wechatUser.getOpenid(), false);
        if( exchangeTime >= maxErrorTime ){
            throw new ServiceException("兑换错误次数超过最大限制次数，锁定当前微信号10分钟！");
        }
        // 查询当前code是否存在
        ExchangeCodeEntity exchangeCodeEntity = getByCode(code);
        if(exchangeCodeEntity == null){
            openIdCacheIncrement(wechatUser.getOpenid(), true);
            throw new ServiceException("未获取到当前激活码！");
        }
        if(exchangeCodeEntity.getStatus() == 1){
            openIdCacheIncrement(wechatUser.getOpenid(), true);
            throw new ServiceException("当前激活码已经被兑换！");
        }
        ProductEntity exchangeProduct = productService.getExchangeProduct();
        //执行添加
        wechatUserService.addQuestionTime(wechatUser.getId(), exchangeProduct.getSku());
        exchangeCodeEntity.setUserId(wechatUser.getId())
                .setStatus(1)
                .setUpdatedTime(new Date());

        updateById(exchangeCodeEntity);
    }

    @Override
    public void getExchangeCode(Integer changeNumber) {

        List<ExchangeCodeEntity> lists =  createExchangeCode(changeNumber);
        // 保存激活码
        saveBatch(lists);
        // excel导出
        writeExcel(lists);
    }

    /**
     * 创建excel导出
     * @param lists
     */
    private void writeExcel(List<ExchangeCodeEntity> lists) {

        ArrayList<ExchangeCodeExportDTO> rows = new ArrayList<>();
        for (int i = 0; i < lists.size(); i++) {
            ExchangeCodeEntity exchangeCodeEntity = lists.get(i);
            ExchangeCodeExportDTO exchangeCodeExportDTO = new ExchangeCodeExportDTO();
            exchangeCodeExportDTO.setIndex(i+1);
            exchangeCodeExportDTO.setCode(exchangeCodeEntity.getCode());
            exchangeCodeExportDTO.setCodeDesc(exchangeCodeEntity.getProductDesc());
            exchangeCodeExportDTO.setCreateTime(DateUtil.format(exchangeCodeEntity.getCreatedTime(), "yyyy-MM-dd"));
            rows.add(exchangeCodeExportDTO);
        }
        ExcelUtil.export( rows, ExchangeCodeExportDTO.getHeaderAlias(), "激活码信息.xlsx" );
    }

    private static final AtomicInteger atomicInteger = new AtomicInteger(0);

    private List<ExchangeCodeEntity> createExchangeCode( Integer changeNumber ) {
        // 先去数据库中查询
        List<ExchangeCodeEntity> list = new ArrayList<>();
        // 查询附赠的产品ID
        ProductEntity exchangeProduct = productService.getExchangeProduct();
        // 交换码
        for (int i = 0; i < changeNumber; i++) {

            ExchangeCodeEntity exchangeCodeEntity = new ExchangeCodeEntity();
            exchangeCodeEntity
                    .setProductId(exchangeProduct.getId())
                    .setProductDesc(exchangeProduct.getDescription())
                    .setCode(UUID.randomUUID().toString())
                    .setCreatedTime(new Date())
                    .setUpdatedTime(new Date());
            // 是否重复
            System.out.println(RandomUtil.randomString(16));
            list.add(exchangeCodeEntity);
        }
        return list;
    }

    /**
     * 错误激活码
     * @return
     */
    public Integer openIdCacheIncrement(String openId, Boolean isIncrement){

        Integer time = openIdCache.get(openId);
        if(ObjectUtil.isNull(time)){
            time = 0;
        }
        if(isIncrement == false){
            return time;
        } else{
            time = time + 1;
        }
        openIdCache.put(openId, time);
        return time;
    }

    /**
     * 根据code获取激活码
     * @param code
     * @return
     */
    private ExchangeCodeEntity getByCode(String code) {
        QueryWrapper<ExchangeCodeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExchangeCodeEntity::getCode, code);
        return getOne(queryWrapper);
    }
}
